package main.UI;

import main.UI.misc.ErrorHandling;
import main.database.DatabaseException;
import main.database.SQLDatabaseManager;
import main.database.entity.Category;
import main.database.entity.Expense;
import org.jdesktop.swingx.JXDatePicker;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.*;
import java.text.ParseException;
import java.util.Date;

public class ExpenseDialog extends JDialog {
    private JPanel contentPane;
    private JButton buttonOK;
    private JButton buttonCancel;
    private JTextField productField;
    private JButton selectProductButton;
    private JFormattedTextField summField;
    private JXDatePicker date;


    //TODO Try to get data from dialog and fire SQLManager method  from outside of dialog
    private Long changedEntryId;

    private static final Color ERROR_BACKGROUND_COLOR = new Color( 255, 215, 215 );

    /*If you want to create new Entry pass 0 as id,
    if you want to change existing entry - pass id of this entry to this constructor with new properties*/
    public ExpenseDialog(Long id, String productName, String dateStr, String price) {
        this();
        changedEntryId = id;
        try {
            date.setDate(GUI.DATE_FORMAT.parse(dateStr));
        }
        catch (ParseException e) {
            e.printStackTrace();
        }
        productField.setText(productName);
        price = price.replace("\u00a0","");    //Not replace " " because it was converted to HTML.
        price = price.replaceAll("<.*?>","");
        summField.setText(price);
        setTitle("Изменить расход");
    }


    public ExpenseDialog() {
        changedEntryId = (long) 0;
        setContentPane(contentPane);
        setModalityType(DEFAULT_MODALITY_TYPE);
        getRootPane().setDefaultButton(buttonOK);
        setResizable(false);
        setTitle("Новый расход");



        productField.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent e) {
                updateColor(productField);
            }
            public void removeUpdate(DocumentEvent e) {
                updateColor(productField);
            }
            public void insertUpdate(DocumentEvent e) {
                updateColor(productField);
            }
        });

        selectProductButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                SelectEntryDialog productDialog = new SelectEntryDialog(true, false);
                centerDialog(productDialog);
                productDialog.pack();
                productDialog.setVisible(true);
                setProductField(productDialog.getItem());
                }
                catch (DatabaseException ex) {
                    ErrorHandling.showError(ex, "Ошибка при обращении к базе данных", false);
                }
            }
        });

        date.setDate(new Date());
        date.setFormats("dd-MM-yyyy");

        //Каретка перемещается туда куда кликают мышкой при фокусе
        summField.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(final MouseEvent e) {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        JTextField tf = (JTextField) e.getSource();
                        int offset = tf.viewToModel(e.getPoint());
                        tf.setCaretPosition(offset);
                    }
                });
            }
        });


        summField.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent e) {
                updateColor(summField);
            }
            public void removeUpdate(DocumentEvent e) {
                updateColor(summField);
            }
            public void insertUpdate(DocumentEvent e) {
                updateColor(summField);
            }
        });

        Action enterAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                buttonOK.doClick(50);
            }
        };

        summField.getInputMap().put(KeyStroke.getKeyStroke("released ENTER"),
                "enterReleased");
        summField.getActionMap().put("enterReleased",
                enterAction);

        buttonOK.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onOK();
            }
        });

        buttonCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        });

// call onCancel() when cross is clicked
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                onCancel();
            }
        });
    }

    private boolean correctInput() {
        if (productField.getText().equals("")) {
            ErrorHandling.showError(null, "Пожалуйста выберите продукт", false);
            productField.setBackground(ERROR_BACKGROUND_COLOR);
            return false;
        }
        double price;
        try {
            price = Expense.convertStringPriceToDouble(summField.getText());
        }
        catch (NumberFormatException e)
        {
            ErrorHandling.showError(null, "Цена не может быть пустой и должна содержать только цифры и разделитель", false);
            summField.setBackground(ERROR_BACKGROUND_COLOR);
            return false;
        }
        if (price <= 0) {
            ErrorHandling.showError(null, "Цена должна быть больше нуля", false);
            summField.setBackground(ERROR_BACKGROUND_COLOR);
            return false;
        }
        if (date.getDate().getTime() > new Date().getTime())
        {
            ErrorHandling.showWarning("Дата позже сегодняшней");
        }
        return true;
    }

    private void onOK() {
        if (!correctInput())
        {
            return;
        }
        try {
            if (changedEntryId!=0) {
                changeEntry();
            }
            else
            {
                addEntry();
            }
        }
        catch (DatabaseException e) {
            ErrorHandling.showError(e, "Ошибка при сохранении расхода в базе данных.", false);
        }
        finally {
            dispose();
        }
    }

    private void addEntry() throws DatabaseException{
        SQLDatabaseManager mng = GUI.getSQLManager();

        String name = productField.getText();
        Double price = Expense.convertStringPriceToDouble(summField.getText());
        String myDate = GUI.DATE_FORMAT.format(date.getDate());

        Expense expense = mng.saveExpense(name, date.getDate(), price, changedEntryId);

        /*if (expense == null)
        {
            JOptionPane.showMessageDialog(null, "Ошибка при добавлении записи.\n" + "Продукт не уникален или отсутствует",
                    "Критическая ошибка ", JOptionPane.ERROR_MESSAGE);
        }*/
        /*else {*/
            String catName;
            if (expense.getProduct().getCategory() == null)
                catName = Category.NO_CATEGORY_WITH_TAGS;
            else
                catName = expense.getProduct().getCategory().getName();
            GUI.addNewExpense(expense.getId(), name, catName, myDate, price);
        /*}*/
    }

    private void changeEntry() throws DatabaseException{
        SQLDatabaseManager mng = GUI.getSQLManager();

        String name = productField.getText();
        Double price = Expense.convertStringPriceToDouble(summField.getText());
        String myDate = GUI.DATE_FORMAT.format(date.getDate());

        Expense expense = mng.saveExpense(name, date.getDate(), price, changedEntryId);

        String catName;
        if (expense.getProduct().getCategory() == null) {
            catName = Category.NO_CATEGORY_WITH_TAGS;
        }
        else
            catName = expense.getProduct().getCategory().getName();
        /*if (expense == null)
        {
            ErrorHandling.showError(null, "Ошибка при изменении записи.", false);
            *//*JOptionPane.showMessageDialog(null, "Ошибка при изменении записи.\n" + "Продукт не уникален или отсутствует",
                    "Критическая ошибка", JOptionPane.ERROR_MESSAGE);*//*
        }
        else*/
            GUI.changeExpenseEntry(name, catName, myDate, price);
    }

    private void onCancel() {
        dispose();
    }

    public void setProductField(String product) {
        productField.setText(product);
    }

    private static void centerDialog(Window dialog) {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = dialog.getSize();
        if (frameSize.height > screenSize.height) {
            frameSize.height = screenSize.height;
        }
        if (frameSize.width > screenSize.width) {
            frameSize.width = screenSize.width;
        }
        dialog.setLocation((screenSize.width - frameSize.width) / 2 - frameSize.width, (screenSize.height - frameSize.height) / 2);
    }

    private void updateColor(Component cmp) {
        cmp.setBackground(null);
    }
}
